package biz

import (
	"context"
	"errors"
	"fmt"
	"github.com/go-kratos/kratos/v2/transport"
	"github.com/go-kratos/kratos/v2/transport/http"
	"github.com/xuri/excelize/v2"
	"io"
	"os"
	v1 "gitlab.cqcb.com/shangyou_mic/dscm-approve-api-pb/api/roses/v1"
	"rosesbff/pkg/util"
	"strings"
	"time"
)

type ArticlesRepo interface {
	GetArticleReaderTaskListCount(ctx context.Context, req *v1.GetArticleReaderTaskListCountRequest) (*v1.GetArticleReaderTaskListCountReply, error)
	GetArticleReaderTaskList(ctx context.Context, req *v1.GetArticleReaderTaskListRequest) (*v1.GetArticleReaderTaskListReply, error)
	GetArticleReaderTaskDoing(ctx context.Context, req *v1.GetArticleReaderTaskDoingRequest) (*v1.GetArticleReaderTaskDoingReply, error)
	PostArticleReaderGrabArticles(ctx context.Context, req *v1.PostArticleReaderGrabArticlesRequest) (*v1.PostArticleReaderGrabArticlesReply, error)
	GetArticleReaderTaskDetails(ctx context.Context, req *v1.GetArticleReaderTaskDetailsRequest) (*v1.GetArticleReaderTaskDetailsReply, error)
	PostArticleEditEditors(ctx context.Context, req *v1.PostArticleEditEditorsRequest) (*v1.PostArticleEditEditorsReply, error)
	PostArticleReaderCommitDraft(ctx context.Context, req *v1.PostArticleReaderCommitDraftRequest) (*v1.PostArticleReaderCommitDraftReply, error)
	PostArticleReaderCommit(ctx context.Context, req *v1.PostArticleReaderCommitRequest) (*v1.PostArticleReaderCommitReply, error)
	PostArticleReaderManualCommitArticle(ctx context.Context, req *v1.PostArticleReaderManualCommitArticleRequest) (*v1.PostArticleReaderManualCommitArticleReply, error)
	PostArticleReaderManualCommitArticleRecord(ctx context.Context, req *v1.PostArticleReaderManualCommitArticleRecordRequest) (*v1.PostArticleReaderManualCommitArticleRecordReply, error)
	GetArticleReaderArticleLists(ctx context.Context, req *v1.GetArticleReaderArticleListsRequest) (*v1.GetArticleReaderArticleListsReply, error)
	GetArticleReaderArticleRecordsLists(ctx context.Context, req *v1.GetArticleReaderArticleRecordsListsRequest) (*v1.GetArticleReaderArticleRecordsListsReply, error)
	PostArticleReaderCancel(ctx context.Context, req *v1.PostArticleReaderCancelRequest) (*v1.PostArticleReaderCancelReply, error)
	PostArticleReaderRefunded(ctx context.Context, req *v1.PostArticleReaderRefundedRequest) (*v1.PostArticleReaderRefundedReply, error)
	PostArticleReaderSubmit(ctx context.Context, req *v1.PostArticleReaderSubmitRequest) (*v1.PostArticleReaderSubmitReply, error)
	GetWithdrawLists(ctx context.Context, req *v1.GetWithdrawListsRequest) (*v1.GetWithdrawListsReply, error)
	PostWithdraw(ctx context.Context, req *v1.PostWithdrawRequest) (*v1.PostWithdrawReply, error)
	GetReaderWorkbench1(ctx context.Context, req *v1.GetReaderWorkbench1Request) (*v1.GetReaderWorkbench1Reply, error)
	GetReaderWorkbench2(ctx context.Context, req *v1.GetReaderWorkbench2Request) (*v1.GetReaderWorkbench2Reply, error)
	PostArticleDelete(ctx context.Context, req *v1.PostArticleDeleteRequest) (*v1.PostArticleDeleteReply, error)
	PostArticleRecordsDelete(ctx context.Context, req *v1.PostArticleRecordsDeleteRequest) (*v1.PostArticleRecordsDeleteReply, error)

	GetArticleVerifierTaskList(ctx context.Context, req *v1.GetArticleVerifierTaskListRequest) (*v1.GetArticleVerifierTaskListReply, error)
	GetArticleVerifierTaskDetails(ctx context.Context, req *v1.GetArticleVerifierTaskDetailsRequest) (*v1.GetArticleVerifierTaskDetailsReply, error)
	PostArticleVerifierUnlockArticle(ctx context.Context, req *v1.PostArticleVerifierUnlockArticleRequest) (*v1.PostArticleVerifierUnlockArticleReply, error)
	PostArticleVerifierArticleUpdate(ctx context.Context, req *v1.PostArticleVerifierArticleUpdateRequest) (*v1.PostArticleVerifierArticleUpdateReply, error)
	GetArticleVerifierTaskRecordsList(ctx context.Context, req *v1.GetArticleVerifierTaskRecordsListRequest) (*v1.GetArticleVerifierTaskRecordsListReply, error)
	GetArticleVerifierTaskManualList(ctx context.Context, req *v1.GetArticleVerifierTaskManualListRequest) (*v1.GetArticleVerifierTaskManualListReply, error)
	GetArticleVerifierArticleRecordsList(ctx context.Context, req *v1.GetArticleVerifierArticleRecordsListRequest) (*v1.GetArticleVerifierArticleRecordsListReply, error)
	PostArticleVerifierManualRecordsUpdate(ctx context.Context, req *v1.PostArticleVerifierManualRecordsUpdateRequest) (*v1.PostArticleVerifierManualRecordsUpdateReply, error)
	PostArticleVerifierScoreUpdate(ctx context.Context, req *v1.PostArticleVerifierScoreUpdateRequest) (*v1.PostArticleVerifierScoreUpdateReply, error)
	PostArticleVerifierClosedUpdate(ctx context.Context, req *v1.PostArticleVerifierClosedUpdateRequest) (*v1.PostArticleVerifierClosedUpdateReply, error)
	PostArticleVerifierRecordsDisposalCreate(ctx context.Context, req *v1.PostArticleVerifierRecordsDisposalCreateRequest) (*v1.PostArticleVerifierRecordsDisposalCreateReply, error)
	GetThisMonthScore(ctx context.Context, req *v1.GetThisMonthScoreRequest) (*v1.GetThisMonthScoreReply, error)
	GetMonthStatistics(ctx context.Context, req *v1.GetMonthStatisticsRequest) (*v1.GetMonthStatisticsReply, error)
	GetMonthSettle(ctx context.Context, req *v1.GetMonthSettleRequest) (*v1.GetMonthSettleReply, error)
	PostMonthSettleApproval(ctx context.Context, req *v1.PostMonthSettleApprovalRequest) (*v1.PostMonthSettleApprovalReply, error)

	GetArticleVerifierWorkbench1(ctx context.Context, req *v1.GetArticleVerifierWorkbench1Request) (*v1.GetArticleVerifierWorkbench1Reply, error)
	GetArticleVerifierWorkbench2(ctx context.Context, req *v1.GetArticleVerifierWorkbench2Request) (*v1.GetArticleVerifierWorkbench2Reply, error)
	GetArticleVerifierWorkbench3(ctx context.Context, req *v1.GetArticleVerifierWorkbench3Request) (*v1.GetArticleVerifierWorkbench3Reply, error)
	GetArticleVerifierWorkbench4(ctx context.Context, req *v1.GetArticleVerifierWorkbench4Request) (*v1.GetArticleVerifierWorkbench4Reply, error)
	GetArticleVerifierWorkbench5(ctx context.Context, req *v1.GetArticleVerifierWorkbench5Request) (*v1.GetArticleVerifierWorkbench5Reply, error)
	GetArticleVerifierWorkbench6(ctx context.Context, req *v1.GetArticleVerifierWorkbench6Request) (*v1.GetArticleVerifierWorkbench6Reply, error)
}

type Articles struct {
	*Basic
	article ArticlesRepo
	common  *Common
}

func NewArticles(
	basic *Basic,
	article ArticlesRepo,
	common *Common,
) (*Articles, error) {
	result := &Articles{
		Basic:   basic,
		article: article,
		common:  common,
	}
	return result, nil
}

func (s *Articles) GetArticleReaderTaskListCount(ctx context.Context, req *v1.GetArticleReaderTaskListCountRequest) (*v1.GetArticleReaderTaskListCountReply, error) {
	return s.article.GetArticleReaderTaskListCount(ctx, req)
}
func (s *Articles) GetArticleReaderTaskList(ctx context.Context, req *v1.GetArticleReaderTaskListRequest) (*v1.GetArticleReaderTaskListReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleReaderTaskList(ctx, req)
}
func (s *Articles) PostArticleReaderGrabArticles(ctx context.Context, req *v1.PostArticleReaderGrabArticlesRequest) (*v1.PostArticleReaderGrabArticlesReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	hours := s.common.Int("B01")
	seconds := hours * 3600
	if seconds <= 0 {
		seconds = 3600
	}
	req.ReaderDuration = &seconds
	return s.article.PostArticleReaderGrabArticles(ctx, req)
}
func (s *Articles) GetArticleReaderTaskDoing(ctx context.Context, req *v1.GetArticleReaderTaskDoingRequest) (*v1.GetArticleReaderTaskDoingReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = userId
	return s.article.GetArticleReaderTaskDoing(ctx, req)
}
func (s *Articles) GetArticleReaderTaskDetails(ctx context.Context, req *v1.GetArticleReaderTaskDetailsRequest) (*v1.GetArticleReaderTaskDetailsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleReaderTaskDetails(ctx, req)
}
func (s *Articles) PostArticleEditEditors(ctx context.Context, req *v1.PostArticleEditEditorsRequest) (*v1.PostArticleEditEditorsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleEditEditors(ctx, req)
}
func (s *Articles) PostArticleReaderCommitDraft(ctx context.Context, req *v1.PostArticleReaderCommitDraftRequest) (*v1.PostArticleReaderCommitDraftReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderCommitDraft(ctx, req)
}
func (s *Articles) PostArticleReaderCommit(ctx context.Context, req *v1.PostArticleReaderCommitRequest) (*v1.PostArticleReaderCommitReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderCommit(ctx, req)
}
func (s *Articles) PostArticleReaderManualCommitArticle(ctx context.Context, req *v1.PostArticleReaderManualCommitArticleRequest) (*v1.PostArticleReaderManualCommitArticleReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderManualCommitArticle(ctx, req)
}
func (s *Articles) PostArticleReaderManualCommitArticleRecord(ctx context.Context, req *v1.PostArticleReaderManualCommitArticleRecordRequest) (*v1.PostArticleReaderManualCommitArticleRecordReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderManualCommitArticleRecord(ctx, req)
}
func (s *Articles) GetArticleReaderArticleLists(ctx context.Context, req *v1.GetArticleReaderArticleListsRequest) (*v1.GetArticleReaderArticleListsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleReaderArticleLists(ctx, req)
}
func (s *Articles) GetArticleReaderArticleRecordsLists(ctx context.Context, req *v1.GetArticleReaderArticleRecordsListsRequest) (*v1.GetArticleReaderArticleRecordsListsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleReaderArticleRecordsLists(ctx, req)
}
func (s *Articles) PostArticleReaderCancel(ctx context.Context, req *v1.PostArticleReaderCancelRequest) (*v1.PostArticleReaderCancelReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderCancel(ctx, req)
}
func (s *Articles) PostArticleReaderRefunded(ctx context.Context, req *v1.PostArticleReaderRefundedRequest) (*v1.PostArticleReaderRefundedReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderRefunded(ctx, req)
}
func (s *Articles) PostArticleReaderSubmit(ctx context.Context, req *v1.PostArticleReaderSubmitRequest) (*v1.PostArticleReaderSubmitReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleReaderSubmit(ctx, req)
}
func (s *Articles) GetWithdrawLists(ctx context.Context, req *v1.GetWithdrawListsRequest) (*v1.GetWithdrawListsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetWithdrawLists(ctx, req)
}
func (s *Articles) PostWithdraw(ctx context.Context, req *v1.PostWithdrawRequest) (*v1.PostWithdrawReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	// todo 提现规则校验 满足条件再放行
	return s.article.PostWithdraw(ctx, req)
}
func (s *Articles) GetReaderWorkbench1(ctx context.Context, req *v1.GetReaderWorkbench1Request) (*v1.GetReaderWorkbench1Reply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetReaderWorkbench1(ctx, req)
}
func (s *Articles) GetReaderWorkbench2(ctx context.Context, req *v1.GetReaderWorkbench2Request) (*v1.GetReaderWorkbench2Reply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetReaderWorkbench2(ctx, req)
}
func (s *Articles) PostArticleDelete(ctx context.Context, req *v1.PostArticleDeleteRequest) (*v1.PostArticleDeleteReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleDelete(ctx, req)
}
func (s *Articles) PostArticleRecordsDelete(ctx context.Context, req *v1.PostArticleRecordsDeleteRequest) (*v1.PostArticleRecordsDeleteReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleRecordsDelete(ctx, req)
}

func (s *Articles) GetArticleVerifierTaskList(ctx context.Context, req *v1.GetArticleVerifierTaskListRequest) (*v1.GetArticleVerifierTaskListReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleVerifierTaskList(ctx, req)
}
func (s *Articles) GetArticleVerifierTaskDetails(ctx context.Context, req *v1.GetArticleVerifierTaskDetailsRequest) (*v1.GetArticleVerifierTaskDetailsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleVerifierTaskDetails(ctx, req)
}
func (s *Articles) PostArticleVerifierUnlockArticle(ctx context.Context, req *v1.PostArticleVerifierUnlockArticleRequest) (*v1.PostArticleVerifierUnlockArticleReply, error) {
	return s.article.PostArticleVerifierUnlockArticle(ctx, req)
}
func (s *Articles) PostArticleVerifierArticleUpdate(ctx context.Context, req *v1.PostArticleVerifierArticleUpdateRequest) (*v1.PostArticleVerifierArticleUpdateReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleVerifierArticleUpdate(ctx, req)
}
func (s *Articles) GetArticleVerifierTaskRecordsList(ctx context.Context, req *v1.GetArticleVerifierTaskRecordsListRequest) (*v1.GetArticleVerifierTaskRecordsListReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleVerifierTaskRecordsList(ctx, req)
}
func (s *Articles) GetArticleVerifierTaskManualList(ctx context.Context, req *v1.GetArticleVerifierTaskManualListRequest) (*v1.GetArticleVerifierTaskManualListReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleVerifierTaskManualList(ctx, req)
}
func (s *Articles) GetArticleVerifierArticleRecordsList(ctx context.Context, req *v1.GetArticleVerifierArticleRecordsListRequest) (*v1.GetArticleVerifierArticleRecordsListReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetArticleVerifierArticleRecordsList(ctx, req)
}
func (s *Articles) PostArticleVerifierManualRecordsUpdate(ctx context.Context, req *v1.PostArticleVerifierManualRecordsUpdateRequest) (*v1.PostArticleVerifierManualRecordsUpdateReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleVerifierManualRecordsUpdate(ctx, req)
}
func (s *Articles) PostArticleVerifierScoreUpdate(ctx context.Context, req *v1.PostArticleVerifierScoreUpdateRequest) (*v1.PostArticleVerifierScoreUpdateReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleVerifierScoreUpdate(ctx, req)
}
func (s *Articles) PostArticleVerifierClosedUpdate(ctx context.Context, req *v1.PostArticleVerifierClosedUpdateRequest) (*v1.PostArticleVerifierClosedUpdateReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleVerifierClosedUpdate(ctx, req)
}
func (s *Articles) PostArticleVerifierRecordsDisposalCreate(ctx context.Context, req *v1.PostArticleVerifierRecordsDisposalCreateRequest) (*v1.PostArticleVerifierRecordsDisposalCreateReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostArticleVerifierRecordsDisposalCreate(ctx, req)
}
func (s *Articles) GetThisMonthScore(ctx context.Context, req *v1.GetThisMonthScoreRequest) (*v1.GetThisMonthScoreReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetThisMonthScore(ctx, req)
}
func (s *Articles) GetMonthStatistics(ctx context.Context, req *v1.GetMonthStatisticsRequest) (*v1.GetMonthStatisticsReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetMonthStatistics(ctx, req)
}
func (s *Articles) GetMonthSettle(ctx context.Context, req *v1.GetMonthSettleRequest) (*v1.GetMonthSettleReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.GetMonthSettle(ctx, req)
}
func (s *Articles) PostMonthSettleApproval(ctx context.Context, req *v1.PostMonthSettleApprovalRequest) (*v1.PostMonthSettleApprovalReply, error) {
	userId := s.GetUserId(ctx)
	req.UserId = &userId
	return s.article.PostMonthSettleApproval(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench1(ctx context.Context, req *v1.GetArticleVerifierWorkbench1Request) (*v1.GetArticleVerifierWorkbench1Reply, error) {
	return s.article.GetArticleVerifierWorkbench1(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench2(ctx context.Context, req *v1.GetArticleVerifierWorkbench2Request) (*v1.GetArticleVerifierWorkbench2Reply, error) {
	return s.article.GetArticleVerifierWorkbench2(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench3(ctx context.Context, req *v1.GetArticleVerifierWorkbench3Request) (*v1.GetArticleVerifierWorkbench3Reply, error) {
	return s.article.GetArticleVerifierWorkbench3(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench4(ctx context.Context, req *v1.GetArticleVerifierWorkbench4Request) (*v1.GetArticleVerifierWorkbench4Reply, error) {
	return s.article.GetArticleVerifierWorkbench4(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench5(ctx context.Context, req *v1.GetArticleVerifierWorkbench5Request) (*v1.GetArticleVerifierWorkbench5Reply, error) {
	return s.article.GetArticleVerifierWorkbench5(ctx, req)
}
func (s *Articles) GetArticleVerifierWorkbench6(ctx context.Context, req *v1.GetArticleVerifierWorkbench6Request) (*v1.GetArticleVerifierWorkbench6Reply, error) {
	return s.article.GetArticleVerifierWorkbench6(ctx, req)
}

func excelColumn(index int) string {
	if index < 0 {
		panic("index cannot be negative")
	}
	index++
	column := ""
	for index > 0 {
		remainder := (index - 1) % 26
		column = fmt.Sprintf("%c%s", 'A'+remainder, column)
		index = (index - 1) / 26
	}
	return column
}

func excelWrite[T any](filename string, data []T, columns []string, handle func(v T) []any) error {
	f := excelize.NewFile()
	defer func() { _ = f.Close() }()

	dataLength := len(data)
	columnsLength := len(columns)

	// 创建一个工作表
	sheet1 := "Sheet1"
	index, err := f.NewSheet(sheet1)
	if err != nil {
		return err
	}
	// 设置表格样式
	{
		styleHeader := &excelize.Style{
			Alignment: &excelize.Alignment{
				Horizontal: "center", // 水平对齐方式
				Vertical:   "center", // 垂直对齐方式
			},
			Font: &excelize.Font{
				Family: "Arial",
				Size:   16,
				Color:  "000000",
			},
		}
		styleHeaderId, err := f.NewStyle(styleHeader)
		if err != nil {
			return err
		}
		err = f.SetRowStyle(sheet1, 1, 1, styleHeaderId)
		if err != nil {
			return err
		}

		// 设置行高
		if err = f.SetRowHeight(sheet1, 1, 50); err != nil {
			return err
		}

		styleBody := &excelize.Style{
			Alignment: &excelize.Alignment{
				Horizontal: "left",   // 水平对齐方式
				Vertical:   "center", // 垂直对齐方式
			},
			Font: &excelize.Font{
				Family: "Arial",
				Size:   16,
				Color:  "000000",
			},
		}
		styleBodyId, err := f.NewStyle(styleBody)
		if err != nil {
			return err
		}
		err = f.SetRowStyle(sheet1, 2, dataLength+1, styleBodyId)
		if err != nil {
			return err
		}
	}
	// 写入列名
	for i, v := range columns {
		cell := fmt.Sprintf("%s1", excelColumn(i))
		if err = f.SetCellValue(sheet1, cell, v); err != nil {
			return err
		}
	}
	// 写入数据
	for i, v := range data {
		values := handle(v)
		if len(values) != columnsLength {
			return fmt.Errorf("the number of columns does not match the number of values")
		}
		for j, w := range values {
			place := fmt.Sprintf("%s%d", excelColumn(j), i+2)
			if err = f.SetCellValue(sheet1, place, w); err != nil {
				return err
			}
		}
	}

	// // 合并单元格
	// {
	// 	if err = f.MergeCell(sheet1, "A22", "F32"); err != nil {
	// 		return err
	// 	}
	// }

	// 设置工作簿的默认工作表
	f.SetActiveSheet(index)
	// 根据指定路径保存文件
	if err = f.SaveAs(filename); err != nil {
		return err
	}
	return nil
}

type Downloads struct {
	ClientViewFilename string // 客户端下载显示文件名称
	Filepath           string // 文件磁盘路径
}

func sendfile[REQ any, RES any](ctx context.Context, req REQ, res RES, fc func(req REQ, res RES) (result *Downloads, err error)) error {
	tr, ok := transport.FromServerContext(ctx)
	if !ok {
		return errors.New("not http")
	}
	trans, okt := tr.(*http.Transport)
	if !okt {
		return errors.New("not http request")
	}
	w := trans.Response()
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Accept-Ranges", "bytes")
	downloads, err := fc(req, res)
	if err != nil {
		return err
	}
	if downloads.ClientViewFilename != "" {
		w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", downloads.ClientViewFilename))
	}
	stat, err := os.Stat(downloads.Filepath)
	if err != nil {
		return err
	}
	w.Header().Set("Content-Length", fmt.Sprintf("%d", stat.Size()))
	file, err := os.OpenFile(downloads.Filepath, os.O_RDONLY, 0600)
	if err != nil {
		return err
	}
	defer func() {
		_ = file.Close()
		_ = os.Remove(downloads.Filepath)
	}()
	_, err = io.Copy(trans.Response(), file)
	if err != nil {
		return err
	}
	return nil
}

// GetArticleVerifierTaskListExports 复核-稿件列表
func (s *Articles) GetArticleVerifierTaskListExports(ctx context.Context, req *v1.GetArticleVerifierTaskListRequest) (*v1.GetArticleVerifierTaskListReply, error) {
	res := &v1.GetArticleVerifierTaskListReply{}
	err := sendfile(ctx, req, res, func(req *v1.GetArticleVerifierTaskListRequest, res *v1.GetArticleVerifierTaskListReply) (*Downloads, error) {
		req.Page = 1
		req.Limit = 10000
		userId := s.GetUserId(ctx)
		req.UserId = &userId
		// req.UserId = tea.Int64(41)
		// req.State = tea.Int32(25)
		reply, err := s.article.GetArticleVerifierTaskList(ctx, req)
		if err != nil {
			return nil, err
		}
		if reply.StatusCode != 200 {
			return nil, errors.New(reply.Message)
		}
		result := &Downloads{
			ClientViewFilename: fmt.Sprintf("%s.xlsx", util.RandomString(32)),
			Filepath:           fmt.Sprintf("%d-%s.xlsx", time.Now().Unix(), util.RandomString(16)),
		}
		filenames := []string{"稿件列表"}
		// 默认全部
		head := []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "状态"}
		if req.State != nil {
			switch *req.State {
			case 1: // 未领取
				head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "截止时间"}
				filenames = append(filenames, "未领取")
			case 9: // 审读中
				head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "审读员", "领取时间"}
				filenames = append(filenames, "审读中")
			case 17: // 待复核
				head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "差错数量", "审读员", "复核员", "提交时间"}
				filenames = append(filenames, "待复核")
			case 25: // 已结案
				head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "差错数量", "审读员", "复核员", "提交时间", "合计得分"}
				filenames = append(filenames, "已结案")
			case 33: // 已超时
				head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "源文连接", "审读员", "领取时间"}
				filenames = append(filenames, "已超时")
			default:
			}
		}
		filenames = append(filenames, util.RandomString(8))
		result.ClientViewFilename = fmt.Sprintf("%s.xlsx", strings.Join(filenames, "-"))
		err = excelWrite(
			result.Filepath,
			reply.Data,
			head,
			func(v *v1.GetArticleVerifierTaskListReply_Data) []any {
				lists := make([]any, 0)
				lists = append(lists, v.Id)
				lists = append(lists, fmt.Sprintf("%s/%s/%s", v.GetMedia(), v.GetPlatform(), v.GetChannelName()))
				lists = append(lists, v.Title)
				if v.PublishAt > 0 {
					lists = append(lists, time.Unix(v.PublishAt, 0).Format(time.DateTime))
				} else {
					lists = append(lists, "")
				}
				lists = append(lists, v.GetSourceUrl())
				if req.State == nil {
					// 查询全部状态
					switch v.State {
					case 1:
						lists = append(lists, "未领取")
					case 9:
						lists = append(lists, "审读中")
					case 17:
						lists = append(lists, "待复核")
					case 25:
						lists = append(lists, "已结案")
					case 33:
						lists = append(lists, "已超时")
					default:
						lists = append(lists, "未知")
					}
				} else {
					// 查询指定状态
					switch *req.State {
					case 1:
						if v.DeadlineAt > 0 {
							lists = append(lists, time.Unix(v.DeadlineAt, 0).Format(time.DateTime))
						} else {
							lists = append(lists, "")
						}
					case 9:
						lists = append(lists, strings.Join(v.Readers, ","))
						if v.ReceiveAt > 0 {
							lists = append(lists, time.Unix(v.ReceiveAt, 0).Format(time.DateTime))
						} else {
							lists = append(lists, "")
						}
					case 17:
						lists = append(lists, v.Records)
						lists = append(lists, strings.Join(v.Readers, ","))
						lists = append(lists, v.VerifierRealName)
						if v.CreatedAt > 0 {
							lists = append(lists, time.Unix(v.CreatedAt, 0).Format(time.DateTime))
						} else {
							lists = append(lists, "")
						}
					case 25:
						lists = append(lists, v.Records)
						lists = append(lists, strings.Join(v.Readers, ","))
						lists = append(lists, v.VerifierRealName)
						if v.CreatedAt > 0 {
							lists = append(lists, time.Unix(v.CreatedAt, 0).Format(time.DateTime))
						} else {
							lists = append(lists, "")
						}
						lists = append(lists, v.TotalScore)
					case 33:
						lists = append(lists, strings.Join(v.Readers, ","))
						if v.ReceiveAt > 0 {
							lists = append(lists, time.Unix(v.ReceiveAt, 0).Format(time.DateTime))
						} else {
							lists = append(lists, "")
						}
					default:
					}
				}
				return lists
			},
		)
		if err != nil {
			return nil, err
		}
		return result, nil
	})
	if err != nil {
		res.StatusCode = 500
		res.Message = err.Error()
		return res, nil
	}
	return res, nil
}

// GetArticleVerifierTaskManualListExports 复核-稿件列表-人工提交
func (s *Articles) GetArticleVerifierTaskManualListExports(ctx context.Context, req *v1.GetArticleVerifierTaskManualListRequest) (*v1.GetArticleVerifierTaskManualListReply, error) {
	res := &v1.GetArticleVerifierTaskManualListReply{}
	err := sendfile(ctx, req, res, func(req *v1.GetArticleVerifierTaskManualListRequest, res *v1.GetArticleVerifierTaskManualListReply) (*Downloads, error) {
		req.Page = 1
		req.Limit = 10000
		userId := s.GetUserId(ctx)
		req.UserId = &userId
		reply, err := s.article.GetArticleVerifierTaskManualList(ctx, req)
		if err != nil {
			return nil, err
		}
		if reply.StatusCode != 200 {
			return nil, errors.New(reply.Message)
		}
		result := &Downloads{
			ClientViewFilename: fmt.Sprintf("%s.xlsx", util.RandomString(32)),
			Filepath:           fmt.Sprintf("%d-%s.xlsx", time.Now().Unix(), util.RandomString(16)),
		}
		filenames := []string{"稿件列表-人工提交"}
		// 默认全部
		head := []string{"ID", "媒体", "问题区域", "标题", "发布时间", "源文连接", "差错数量", "审读员", "复核员", "提交时间", "状态"}
		filenames = append(filenames, util.RandomString(8))
		result.ClientViewFilename = fmt.Sprintf("%s.xlsx", strings.Join(filenames, "-"))
		err = excelWrite(
			result.Filepath,
			reply.Data,
			head,
			func(v *v1.GetArticleVerifierTaskManualListReply_Data) []any {
				lists := make([]any, 0)
				lists = append(lists, v.Id)
				lists = append(lists, v.GetMedia())
				lists = append(lists, v.GetProblemAreaManual())
				lists = append(lists, v.Title)
				if v.PublishAt > 0 {
					lists = append(lists, time.Unix(v.PublishAt, 0).Format(time.DateTime))
				} else {
					lists = append(lists, "")
				}
				lists = append(lists, v.GetSourceUrl())
				lists = append(lists, v.GetRecords())
				lists = append(lists, strings.Join(v.GetReaders(), ","))
				lists = append(lists, v.GetVerifierRealName())
				if v.CreatedAt > 0 {
					lists = append(lists, time.Unix(v.CreatedAt, 0).Format(time.DateTime))
				} else {
					lists = append(lists, "")
				}
				switch v.GetState() {
				case 17:
					lists = append(lists, "待复核")
				case 25:
					lists = append(lists, "已结案")
				default:
					lists = append(lists, "未知")
				}
				return lists
			},
		)
		if err != nil {
			return nil, err
		}
		return result, nil
	})
	if err != nil {
		res.StatusCode = 500
		res.Message = err.Error()
		return res, nil
	}
	return res, nil
}

// GetArticleVerifierArticleRecordsListExports 复核-差错列表
func (s *Articles) GetArticleVerifierArticleRecordsListExports(ctx context.Context, req *v1.GetArticleVerifierArticleRecordsListRequest) (*v1.GetArticleVerifierArticleRecordsListReply, error) {
	res := &v1.GetArticleVerifierArticleRecordsListReply{}
	err := sendfile(ctx, req, res, func(req *v1.GetArticleVerifierArticleRecordsListRequest, res *v1.GetArticleVerifierArticleRecordsListReply) (*Downloads, error) {
		req.Page = 1
		req.Limit = 10000
		userId := s.GetUserId(ctx)
		req.UserId = &userId
		reply, err := s.article.GetArticleVerifierArticleRecordsList(ctx, req)
		if err != nil {
			return nil, err
		}
		if reply.StatusCode != 200 {
			return nil, errors.New(reply.Message)
		}
		result := &Downloads{
			ClientViewFilename: fmt.Sprintf("%s.xlsx", util.RandomString(32)),
			Filepath:           fmt.Sprintf("%d-%s.xlsx", time.Now().Unix(), util.RandomString(16)),
		}
		filenames := []string{"差错列表"}
		// 默认机器巡检
		var head []string
		switch req.FromType {
		case 1: // 机器巡检
			head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "差错类型", "问题词语", "修改建议", "严重程度", "审读结果", "状态", "审读员", "提交时间", "得分", "复核员", "标签", "处置意见"}
			filenames = append(filenames, "机器巡检")
		case 2: // 人工审核
			head = []string{"ID", "媒体/平台/频道", "标题", "发布时间", "差错位置", "差错类型", "差错原因", "差错描述", "更改建议", "截图", "审读员", "提交时间", "状态", "得分", "标签", "处置意见"}
			filenames = append(filenames, "人工审核")
		case 3: // 人工提交
			head = []string{"ID", "媒体", "问题区域", "标题", "发布时间", "差错位置", "差错类型", "差错原因", "差错描述", "更改建议", "截图", "审读员", "提交时间", "状态", "得分", "复核员", "标签", "处置意见"}
			filenames = append(filenames, "人工提交")
		default:
			return nil, errors.New("未知差错类型")
		}
		filenames = append(filenames, util.RandomString(8))
		result.ClientViewFilename = fmt.Sprintf("%s.xlsx", strings.Join(filenames, "-"))
		err = excelWrite(
			result.Filepath,
			reply.Data,
			head,
			func(v *v1.GetArticleVerifierArticleRecordsListReply_Data) []any {
				lists := make([]any, 0)
				lists = append(lists, v.Id)
				titlePublishAt := func() {
					lists = append(lists, v.GetTitle())
					if v.PublishAt > 0 {
						lists = append(lists, time.Unix(v.PublishAt, 0).Format(time.DateTime))
					} else {
						lists = append(lists, "")
					}
				}
				level := func() {
					switch v.GetErrorLevel() {
					case 1:
						lists = append(lists, "疑错")
					case 2:
						lists = append(lists, "一般")
					case 3:
						lists = append(lists, "严重")
					default:
						lists = append(lists, "未知")
					}
				}
				readerResult := func() {
					switch v.GetReaderCheck() {
					case 1:
						lists = append(lists, "判定有误")
					case 2:
						lists = append(lists, "判定无误")
					default:
						lists = append(lists, "未判定")
					}
				}
				state := func() {
					switch v.GetState() {
					case 1:
						lists = append(lists, "未领取")
					case 9:
						lists = append(lists, "审读中")
					case 17:
						lists = append(lists, "待复核")
					case 25:
						lists = append(lists, "已结案")
					case 33:
						lists = append(lists, "已超时")
					default:
						lists = append(lists, "未知")
					}
				}
				createdAt := func() {
					if v.CreatedAt > 0 {
						lists = append(lists, time.Unix(v.CreatedAt, 0).Format(time.DateTime))
					} else {
						lists = append(lists, "")
					}
				}
				disposal := func() {
					disposals := make([]string, 0)
					for _, w := range v.GetDisposal() {
						tmp := ""
						if w.Content != nil {
							tmp = *w.Content
						}
						if tmp == "" {
							continue
						}
						disposals = append(disposals, tmp)
					}
					lists = append(lists, strings.Join(disposals, ","))
				}
				switch req.FromType {
				case 1:
					lists = append(lists, fmt.Sprintf("%s/%s/%s", v.GetMedia(), v.GetPlatform(), v.GetChannelName()))
					titlePublishAt()
					lists = append(lists, v.GetErrorType())
					lists = append(lists, v.GetErrorContent())
					lists = append(lists, v.GetErrorModifyAdvice())
					level()
					readerResult()
					state()
					lists = append(lists, v.GetReaderRealName())
					createdAt()
					lists = append(lists, v.GetReaderScore())
					lists = append(lists, v.GetVerifierRealName())
					lists = append(lists, v.GetNote())
					disposal()
				case 2:
					lists = append(lists, fmt.Sprintf("%s/%s/%s", v.GetMedia(), v.GetPlatform(), v.GetChannelName()))
					titlePublishAt()
					lists = append(lists, v.GetErrorLocation())
					lists = append(lists, v.GetErrorType())
					lists = append(lists, v.GetErrorReason())
					lists = append(lists, v.GetErrorMessage())
					lists = append(lists, v.GetErrorModifyAdvice())
					lists = append(lists, v.GetErrorUrls())
					lists = append(lists, v.GetReaderRealName())
					createdAt()
					state()
					lists = append(lists, v.GetReaderScore())
					lists = append(lists, v.GetNote())
					disposal()
				case 3:
					lists = append(lists, v.GetMedia())
					lists = append(lists, v.GetProblemAreaManual())
					titlePublishAt()
					lists = append(lists, v.GetErrorLocation())
					lists = append(lists, v.GetErrorType())
					lists = append(lists, v.GetErrorReason())
					lists = append(lists, v.GetErrorMessage())
					lists = append(lists, v.GetErrorModifyAdvice())
					lists = append(lists, v.GetErrorUrls())
					lists = append(lists, v.GetReaderRealName())
					createdAt()
					state()
					lists = append(lists, v.GetReaderScore())
					lists = append(lists, v.GetVerifierRealName())
					lists = append(lists, v.GetNote())
					disposal()
				default:
				}
				return lists
			},
		)
		if err != nil {
			return nil, err
		}
		return result, nil
	})
	if err != nil {
		res.StatusCode = 500
		res.Message = err.Error()
		return res, nil
	}
	return res, nil
}

// todo 导出台账
